package com.project.class3_28.bean.impl;

import com.project.class3_28.bean.Column;
import com.project.class3_28.bean.Table;

import java.awt.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.*;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

public class BaseDao {
    /**连接对象*/
    protected Connection con ;
    /**SQL语句执行对象*/
    protected PreparedStatement ps;
    /**结果集对象*/
    protected ResultSet rs;

    /**
     * 建立连接
     */
    public void setConnection(){
        try {
            Class.forName("com.mysql.jdbc.Driver");
            this.con = DriverManager.getConnection("jdbc:mysql://localhost:12345/db?characterEncoding=utf-8",
                    "root","lovo");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 关闭连接
     */
    public void closeConnection(){
        try {
            if (rs!=null) {
                rs.close();
            }
            if (ps!=null) {
                ps.close();
            }
            if (con!=null) {
                con.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
    public void updateDB(String sql,Object... valueArray){
        this.setConnection();
        try {
            ps = con.prepareStatement(sql);
            for (int i=0;i<valueArray.length;i++){
                ps.setObject(i+1,valueArray[i]);
            }
            ps.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            this.closeConnection();
        }
    }

//    /**
//     * 执行查询
//     * @param sql 查询的SQL语句
//     * @param beanClass 查询需要封装的实体对象
//     * @param valueArray 查询条件值列表
//     * @return 实体类集合
//     */
//    public List findDB(String sql,Class beanClass,Object...valueArray){
//        List list = new ArrayList();
//        this.setConnection();
//        try {
//            ps = con.prepareStatement(sql);
//            for (int i=0;i<valueArray.length;i++){
//                ps.setObject(i+1,valueArray[i]);
//            }
//            rs = ps.executeQuery();
//            while (rs.next()){
//                //产生实体类对象
//                Object beanObj = beanClass.getConstructor().newInstance();
//                //得到实体类中的属性列表
//                Field[] farray = beanClass.getDeclaredFields();
//                for (Field f : farray){
//                    //去掉访问修饰符检查
//                    f.setAccessible(true);
//                    //从结果集中得到值
//                    Object value = rs.getObject(f.getName());
//                    //f.getType得到属性类型，返回属性类型的Class对象
//                    if (f.getType() == LocalDate.class){
//                        f.set(beanObj,LocalDate.parse(value.toString()));
//                    }else {
//                        f.set(beanObj, value);
//                    }
//                }
//                list.add(beanObj);
//            }
//        } catch (Exception throwables) {
//            throwables.printStackTrace();
//        }finally {
//            closeConnection();
//        }
//
//        return list;
//    }

    /**
     * 执行查询
     * @param sql 查询的SQL语句
     * @param beanClass 查询需要封装的实体对象
     * @param valueArray 查询条件值列表
     * @return 实体类集合
     */
//    public List findDB(String sql,Class beanClass, Object...valueArray){
//        List list = new ArrayList();
//        this.setConnection();
//        try {
//            ps = con.prepareStatement(sql);
//            for (int i=0;i<valueArray.length;i++){
//                ps.setObject(i+1,valueArray[i]);
//            }
//            rs = ps.executeQuery();
//            //得到结果集信息对象
//            ResultSetMetaData rm = rs.getMetaData();
//            //得到查询列的个数
//            int columnCount = rm.getColumnCount();
//            System.out.println(columnCount);
//            while (rs.next()){
//                //产生实体类对象
//                Object beanObj = beanClass.getConstructor().newInstance();
//                for (int i=1;i<=columnCount;i++){
//                    //得到查询列的列名
//                    String columnName = rm.getColumnName(i);
//                    //从结果集中，得到指定对应列对应的值
//                    Object value = rs.getObject(columnName);
//
//                    //根据属性名，得到属性对象
//                    Field f = beanClass.getDeclaredField(columnName);
//                    f.setAccessible(true);
//
//                    if (f.getType()==LocalDate.class){
//                        f.set(beanObj,LocalDate.parse(value.toString()));
//                    }else {
//                        f.set(beanObj,value);
//                    }
//                }
//                list.add(beanObj);
//            }
//        } catch (Exception throwables) {
//            throwables.printStackTrace();
//        }finally {
//            closeConnection();
//        }
//        return list;
//    }

    public List findDB(String sql,Class beanClass,Object...valueArray){
        List list = new ArrayList();
        this.setConnection();
        try {
            ps = con.prepareStatement(sql);
            for (int i=0;i<valueArray.length;i++){
                ps.setObject(i+1,valueArray[i]);
            }
            rs = ps.executeQuery();
            //得到结果集信息对象
            ResultSetMetaData rm = rs.getMetaData();
            //得到查询列的个数
            int columnCount = rm.getColumnCount();
            System.out.println(columnCount);
            while (rs.next()){
                //产生实体类对象
                Object beanObj =  beanClass.getConstructor().newInstance();
                for (int i=1;i<=columnCount;i++){
                    //得到查询列的列名
                    String columnName = rm.getColumnName(i);
                    //从结果集中，得到指定对应列对应的数据
                    Object value = rs.getObject(columnName);

                    //根据列名得到属性对象
                    Field f = this.getFieldByColumn(beanClass,columnName);
                    //根据列名，得到方法名
                    String methodName = getMethodName(f.getName());


                    if (f.getType()==LocalDate.class){
                        value = LocalDate.parse(value.toString());
                    }
                    //得到方法对象
                    Method m = beanClass.getMethod(methodName,f.getType());
                    //执行方法
                    m.invoke(beanObj,value);
                }
                list.add(beanObj);
            }
        } catch (Exception throwables) {
            throwables.printStackTrace();
        }finally {
            closeConnection();
        }
        return list;
    }

    /**
     * 根据列名得到属性对象
     * @param beanClass 实体类类模板
     * @param columnName 列名
     * @return 属性对象
     */
    public Field getFieldByColumn(Class beanClass,String columnName){
        //得到该类的属性列表
        Field[] farray = beanClass.getDeclaredFields();
        for (Field f : farray){
            //判断属性是否存在Column注解
            if (f.isAnnotationPresent(Column.class)){
                //取出属性的Column注解
                Column c = f.getAnnotation(Column.class);
                if (c.value().equals(columnName)){
                    return f;
                }
            }
        }
        return null;
    }
    /**
     * 根据列名，得到方法名
     * @param columnName 列名
     * @return 方法名
     */
    private String getMethodName(String columnName){
        //将首字母变成大写
        String s = columnName.substring(0,1).toUpperCase();
        return "set"+s+columnName.substring(1);
    }

    /**
     * 添加
     * @param beanObj 对象
     */
    public void add(Object beanObj){
        String sql = "insert into ";
        Class beanClass = beanObj.getClass();
        if (beanClass.isAnnotationPresent(Table.class)){
            Table t = (Table) beanClass.getAnnotation(Table.class);
            sql += t.tableName()+"(";
        }
        //得到类的属性列表
        Field[] farray = beanClass.getDeclaredFields();
        for (int i=0;i<farray.length;i++){
            //得到需要插入的列
            String columnName = getColumnByField(farray[i]);
            if (i==farray.length-1){
                sql += columnName+") values (";
                break;
            }
            sql += columnName+",";
        }
        for (int i=0;i<farray.length;i++){
            if (i==farray.length-1){
                sql += "?)";
                break;
            }
            sql += "?,";
        }
        this.setConnection();
        try {
            ps = con.prepareStatement(sql);
            for (int i=0;i<farray.length;i++){
                Method m = beanClass.getMethod(farray[i].getName());
                ps.setObject(i+1,m.invoke(beanObj));
            }
        } catch (Exception throwables) {
            throwables.printStackTrace();
        }finally {
            closeConnection();
        }

    }

    /**
     * 根据属性获取列名
     * @param field 属性
     * @return 列名
     */
    public String getColumnByField(Field field){
        if (field.isAnnotationPresent(Column.class)){
            Column c = field.getAnnotation(Column.class);
            return c.value();
        }
        return null;
    }
    /**
     * 根据属性名，得到方法名
     * @param fieldName 属性名
     * @return 方法名
     */
    private String getMethod(String fieldName){
        //将首字母变成大写
        String s = fieldName.substring(0,1).toUpperCase();
        return "get"+s+fieldName.substring(1);
    }
}
